﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace XCI.Helper
{
    /// <summary>
    /// 调试操作类
    /// </summary>
    public static class DebugHelper
    {
        private static readonly object WriteLogLockObject = new object();

        /// <summary>
        /// 输出调试信息到控制台
        /// </summary>
        /// <param name="msg">调试消息</param>
        /// <param name="startMilliSecond">代码执行的开始毫秒数</param>
        public static void DebugConsole(string msg, int? startMilliSecond = null)
        {
#if DEBUG
            int tickCount = Environment.TickCount;
            string className = string.Empty;
            string methodName = string.Empty;
            var trace = new StackTrace();
            var sf = trace.GetFrame(1);
            var method1 = (sf.GetMethod());
            if (method1.DeclaringType != null)
            {
                className = method1.DeclaringType.FullName;
                methodName = method1.Name;
            }

            var timeString = string.Empty;
            if (startMilliSecond != null)
            {
                TimeSpan ts = TimeSpan.FromMilliseconds(tickCount - startMilliSecond.Value);
                timeString = DateTimeHelper.GetTimeString(ts);
                if (string.IsNullOrEmpty(timeString))
                {
                    timeString = string.Concat(ts.TotalMilliseconds, "毫秒");
                }
            }
            string message = $"{DateTimeHelper.FormatDateHasSecond(DateTime.Now)} Debug {className}.{methodName} {msg} 耗时：{timeString}";
            System.Diagnostics.Debug.WriteLine(message);
#endif
        }

        /// <summary>
        /// TryCatch包装
        /// </summary>
        /// <param name="enabled">是否启用TryCatch包装</param>
        /// <param name="bodyAction">执行回调</param>
        /// <param name="catchAction">Catch回调</param>
        public static void TryCatch(bool enabled, Action bodyAction, Action<Exception> catchAction)
        {
            if (enabled)
            {
                bodyAction();
            }
            else
            {
                try
                {
                    bodyAction();
                }
                catch (Exception e)
                {
                    catchAction?.Invoke(e);
                }
            }
        }


        /// <summary>
        /// 开始计时器
        /// </summary>
        public static Stopwatch StartWatch()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            return watch;
        }

        /// <summary>
        /// 结束计时器
        /// </summary>
        /// <param name="watch"></param>
        public static TimeSpan EndWatch(Stopwatch watch)
        {
            watch.Stop();
            return watch.Elapsed;
        }

        /// <summary>
        /// 开始计算程序执行时间(xx毫秒)
        /// </summary>
        /// <param name="action">执行函数</param>
        /// <returns>返回程序执行的时间</returns>
        public static string StartWatchAsString(Action action)
        {
            var watch = StartWatch();
            action.Invoke();
            TimeSpan ts = EndWatch(watch);
            string timeString = DateTimeHelper.GetTimeString(ts);
            if (string.IsNullOrEmpty(timeString))
            {
                timeString = string.Concat(ts.TotalMilliseconds, "毫秒");
            }
            return timeString;
        }

        /// <summary>
        /// 记录错误信息到文件中
        /// </summary>
        /// <param name="e">一次对象</param>
        public static void CatchLogFile(Exception e)
        {
            // WriteFileCore(BuildExceptionInfo(e));
        }

        /// <summary>
        /// 记录错误信息到文件中
        /// </summary>
        /// <param name="msg">日志内容</param>
        public static void CatchLogFile(string msg)
        {
            // StackTrace st = new StackTrace();
            // StackFrame sf = st.GetFrame(1);
            // var method = sf.GetMethod();
            // string message =
            //     $"{DateTimeHelper.FormatDateHasSecond(DateTime.Now)} {method.DeclaringType?.FullName}.{method.Name} {msg}";
            // WriteFileCore(message);
        }

        private static void WriteFileCore(string message)
        {
//             lock (WriteLogLockObject)
//             {
//                 string folder = IOHelper.RootDirectory;
//                 string fileName = "Catch-" + DateTimeHelper.FormatDate(DateTime.Now, "yyyy-MM-dd") + ".log";
//                 string path = Path.Combine(folder, "log", fileName);
//                 IOHelper.CreateDirectoryByPath(path);
//
//                 try
//                 {
//                     StreamWriter streamWriter = !File.Exists(path) ? File.CreateText(path) : File.AppendText(path);
//                     using (streamWriter)
//                     {
//                         streamWriter.WriteLine(message);
//                         streamWriter.Flush();
//                     }
//                 }
//                 catch (Exception e)
//                 {
// #if DEBUG
//                     Debug.WriteLine(e.Message);
// #endif
//                 }
//             }
        }

        /// <summary>
        /// 生成所有异常的消息
        /// </summary>
        /// <param name="es">异常集合对象</param>
        public static string BuildAllMessage(params Exception[] es)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in es)
            {
                var list = new List<string>();
                Exception current = item;
                while (current != null)
                {
                    list.Add(current.Message);
                    current = current.InnerException;
                }

                // list.Reverse();
                list.ForEach(p => sb.AppendLine(p));
            }
            return sb.ToString();
        }

        /// <summary>
        /// 生成异常详细信息
        /// </summary>
        /// <param name="ex">异常对象</param>
        public static string BuildAllStackTrace(Exception ex)
        {
            Exception current = ex;
            StringBuilder sb = new StringBuilder();
            while (current != null)
            {
                sb.AppendLine("异常消息：" + current.Message);
                sb.AppendLine("异常类型：" + current.GetType().FullName);
                sb.AppendLine("异常方法：" + (current.TargetSite == null ? null : current.TargetSite.Name));
                sb.AppendLine("异常源：" + current.Source);
                if (current.StackTrace != null)
                {
                    sb.AppendLine("异常堆栈：");
                    sb.AppendLine(current.StackTrace);
                }
                if (current.InnerException != null)
                {
                    sb.AppendLine();
                    sb.AppendLine("---------------------------------");
                    sb.AppendLine("内部异常：");
                }
                current = current.InnerException;
            }
            return sb.ToString();
        }
    }
}